﻿#region << 文 件 说 明 >>
/*----------------------------------------------------------------
// 文件名称：DetailVM
// 创 建 者：杨程
// 创建时间：2022/2/18 9:46:29
// 文件版本：V1.0.0
// ===============================================================
// 功能描述：
//		
//
//----------------------------------------------------------------*/
#endregion




namespace Vampirewal.Core.SimpleMVVM;

/// <summary>
/// 单独Detail的VM
/// </summary>
/// <typeparam name="TDtlEntity"></typeparam>
public abstract partial class DetailVM<TDtlEntity> : ViewModelBase where TDtlEntity : DetailBaseModel, new()
{
    #region 构造函数
    /// <summary>
    /// 
    /// </summary>
    public DetailVM() : base()
    {
        if (DtlEntity == null)
        {
            var ctor = typeof(TDtlEntity).GetConstructor(Type.EmptyTypes);
            DtlEntity = ctor.Invoke(null) as TDtlEntity;
        }


        DetailVmInitData();
    }

    /// <summary>
    /// 
    /// </summary>
    /// <param name="rep"></param>
    public DetailVM(SqlSugarRepository<TDtlEntity> rep) : base()
    {
        if (DtlEntity == null)
        {
            var ctor = typeof(TDtlEntity).GetConstructor(Type.EmptyTypes);
            DtlEntity = ctor.Invoke(null) as TDtlEntity;
        }

        Rep = rep;
        DetailVmInitData();
    }


    #endregion

    #region 属性

    /// <summary>
    /// 明细实体类
    /// </summary>
    [ObservableProperty]
    private TDtlEntity dtlEntity;

    /// <summary>
    /// Dtl数据库
    /// </summary>
    protected SqlSugarRepository<TDtlEntity> Rep { get; set; }
    #endregion

    #region 公共方法
    /// <summary>
    /// 直连数据库的话需要通过调用该方法获取Entity
    /// </summary>
    /// <param name="DtlId"></param>
    protected virtual void GetById(string DtlId)
    {
        DtlEntity = Rep.Single(w => w.DtlId == DtlId);
    }

    /// <summary>
    /// 通过HttpClient等方式获取的Entity可调用该方法赋值
    /// </summary>
    /// <param name="t"></param>
    protected virtual void SetEntity(TDtlEntity t)
    {
        if (t != null)
            DtlEntity = t;
    }
    #endregion

    #region 私有方法
    /// <summary>
    /// 验证数据库连接
    /// </summary>
    /// <param name="DbName"></param>
    /// <exception cref="Exception"></exception>
    private void CheckClient(string DbName)
    {

        if (string.IsNullOrEmpty(DtlEntity.BillId))
        {
            throw new Exception("明细类的BillId不能为空！");
        }

        if (DbName != "default")
        {
            Rep.Context.ChangeDatabase(DbName);
        }

    }


    private void DoCRUD(string OperationCommand)
    {
        Rep.BeginTran();
        try
        {
            switch (OperationCommand)
            {
                case "add":
                    Rep.Insert(DtlEntity);
                    break;
                case "update":
                    Rep.Update(DtlEntity, null, "DtlId");
                    break;
                case "delete":
                    {
                        Type type = typeof(TDtlEntity);

                        var Interfaces = type.GetInterfaces();

                        foreach (var Interface in Interfaces)
                        {
                            if (Interface == typeof(IPersistModel))
                            {
                                (DtlEntity as IPersistModel).IsDelete = true;
                                //Entity.UpdateBy = SystemDataContext.GetInstance().loginUserInfo?.ITCode;
                                //Entity.UpdateTime = DateTime.Now;
                            }
                        }

                        Rep.Delete(DtlEntity);
                    }

                    break;
            }


            Rep.CommitTran();
        }
        catch
        {
            Rep.RollbackTran();
        }
        finally
        {
            Rep.Context.ChangeDatabase("default");
        }
    }

    private async Task DoCRUDasync(string OperationCommand)
    {
        Rep.BeginTran();
        try
        {
            switch (OperationCommand)
            {
                case "add":
                    await Rep.InsertAsync(DtlEntity);
                    break;
                case "update":
                    await Rep.UpdateAsync(DtlEntity);
                    break;
                case "delete":
                    {
                        Type type = typeof(TDtlEntity);

                        var Interfaces = type.GetInterfaces();

                        foreach (var Interface in Interfaces)
                        {
                            if (Interface == typeof(IPersistModel))
                            {
                                (DtlEntity as IPersistModel).IsDelete = true;
                                //Entity.UpdateBy = SystemDataContext.GetInstance().loginUserInfo?.ITCode;
                                //Entity.UpdateTime = DateTime.Now;
                            }
                        }

                        await Rep.DeleteAsync(DtlEntity);
                    }

                    break;
            }


            Rep.CommitTran();
        }
        catch
        {
            Rep.RollbackTran();
        }
        finally
        {
            Rep.Context.ChangeDatabase("default");
        }
    }
    #endregion

    #region 命令

    #endregion

    #region 重写
    /// <summary>
    /// BillVM的数据化方法
    /// </summary>
    public virtual void DetailVmInitData()
    {

    }

    /// <summary>
    /// 执行entity的新增到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public virtual void DoAdd(string DbName = "default")
    {
        CheckClient(DbName);

        //Entity.CreateBy = SystemDataContext.GetInstance().loginUserInfo.ITCode;

        DoCRUD("add");
    }

    /// <summary>
    /// 异步执行entity的新增到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public async virtual void DoAddAsync(string DbName = "default")
    {
        CheckClient(DbName);

        //Entity.CreateBy = SystemDataContext.GetInstance().loginUserInfo.ITCode;

        await DoCRUDasync("add");
    }

    /// <summary>
    /// 执行entity的修改到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public virtual void DoUpdate(string DbName = "default")
    {
        CheckClient(DbName);

        //Entity.UpdateBy = SystemDataContext.GetInstance().loginUserInfo.ITCode;

        DoCRUD("update");
    }

    /// <summary>
    /// 异步执行entity的修改到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public async virtual void DoUpdateAsync(string DbName = "default")
    {
        CheckClient(DbName);

        //Entity.UpdateBy = SystemDataContext.GetInstance().loginUserInfo.ITCode;

        await DoCRUDasync("update");
    }

    /// <summary>
    /// 执行entity的删除到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public virtual void DoDelete(string DbName = "default")
    {
        CheckClient(DbName);

        DoCRUD("delete");
    }

    /// <summary>
    /// 异步执行entity的删除到数据库操作
    /// </summary>
    /// <param name="DbName"></param>
    public async virtual void DoDeleteAsync(string DbName = "default")
    {
        CheckClient(DbName);

        await DoCRUDasync("delete");
    }


    #endregion
}

/*
 * 暂时没想到应该怎么写，TDto需在构建TDetail的时候传进去，才能监控到值的变化，如果通过下面的方式创建，那么额外的代码量也挺大的
 */

//public class DetailChange<TDetail,TDto>:ViewModelBase where TDetail : DetailItemChangeBaseModel<TDto>, new() where TDto : TopModel, new()
//{
//    public DetailChange()
//    {
//        if (DtlEntity == null)
//        {

//            var dto= typeof(TDto).GetConstructor(Type.EmptyTypes);
//            var DTO= dto.Invoke(null) as TDto;

//            var ctor = typeof(TDetail).GetConstructor( new Type[]{ typeof(TDto)} );
//            DtlEntity = ctor.Invoke(new object[] { DTO }) as TDetail;
//        }
//    }

//    private TDetail _DtlEntity;
//    /// <summary>
//    /// 明细实体类
//    /// </summary>
//    public TDetail DtlEntity
//    {
//        get { return _DtlEntity; }
//        set { _DtlEntity = value; DoNotify(); }
//    }
//}
